//
//  SVGPath.m
//  Shake and Bake
//
//  Created by Antoine Quint on 13/08/07.
//  Copyright 2007 __MyCompanyName__. All rights reserved.
//

#import "SVGPath.h"
#import "SVGPathParser.h"

@implementation SVGPath

- (id)initWithAttributeDict:(NSDictionary *)attributesDict andView:(Canvas *)aView
{
  [super initWithAttributeDict:attributesDict andView:aView];
	if (self) {
		// parse attribute values
		path = [SVGPath buildPathWithData:[attributes objectForKey:@"d"]];
		CGRect pathBounds = CGPathGetBoundingBox(path);
		self.bounds = CGRectMake( 0.0f,
		                          0.0f,
		                          pathBounds.size.width + pathBounds.origin.x + strokeWidth / 2,
		                          pathBounds.size.height + pathBounds.origin.y + strokeWidth / 2);
		self.name = @"path";
	}
	return self;
}

/***** PARSER *****/

+ (CGPathRef)buildPathWithData:(NSString *)data
{
	CGMutablePathRef path = CGPathCreateMutable();
	CGPoint currentPoint = CGPointMake(0.0f, 0.0f);
	CGPoint currentCenter = CGPointMake(0.0f, 0.0f);
	// begin parsing
	SVG_path_command *command;
	float *p;
	int type;
  SVG_path_begin_parsing([data UTF8String]);
	// parse
  //NSLog(@"Start parsing path");
	while (command = SVG_path_next_command()) {
		type = command->type;
		p = command->params;
    float x, y, x1, y1, x2, y2;
		if (type == SVG_path_MOVETO_ABSOLUTE) {
			currentPoint.x = p[0];
			currentPoint.y = p[1];
			currentCenter.x = p[0];
			currentCenter.y = p[1];
			CGPathMoveToPoint(path, NULL, currentPoint.x, currentPoint.y);
			//NSLog(@"M: %f, %f", p[0], p[1]);
		}
		else if (type == SVG_path_MOVETO_RELATIVE) {
			currentPoint.x += p[0];
			currentPoint.y += p[1];
			currentCenter.x += p[0];
			currentCenter.y += p[1];
			CGPathMoveToPoint(path, NULL, currentPoint.x, currentPoint.y);
			//NSLog(@"m: %f, %f", p[0], p[1]);
		}
		else if (type == SVG_path_CLOSEPATH) {
      CGPathCloseSubpath(path);
			//NSLog(@"path closed");
		}
		else if (type == SVG_path_LINETO_ABSOLUTE) {
			currentPoint.x = p[0];
			currentPoint.y = p[1];
			currentCenter.x = p[0];
			currentCenter.y = p[1];
      CGPathAddLineToPoint(path, NULL, currentPoint.x, currentPoint.y);
			//NSLog(@"L: %f, %f", p[0], p[1]);
		}
		else if (type == SVG_path_LINETO_RELATIVE) {
			currentPoint.x += p[0];
			currentPoint.y += p[1];
			currentCenter.x += p[0];
			currentCenter.y += p[1];
      CGPathAddLineToPoint(path, NULL, currentPoint.x, currentPoint.y);
			//NSLog(@"l: %f, %f", p[0], p[1]);
		}
		else if (type == SVG_path_HORIZONTAL_LINETO_ABSOLUTE) {
			currentPoint.x = p[0];
			currentCenter.x = p[0];
      CGPathAddLineToPoint(path, NULL, currentPoint.x, currentPoint.y);
			//NSLog(@"H: %f", p[0]);
		}
		else if (type == SVG_path_HORIZONTAL_LINETO_RELATIVE) {
			currentPoint.x += p[0];
			currentCenter.x += p[0];
      CGPathAddLineToPoint(path, NULL, currentPoint.x, currentPoint.y);
			//NSLog(@"h: %f", p[0]);
		}
		else if (type == SVG_path_VERTICAL_LINETO_ABSOLUTE) {
			currentPoint.y = p[0];
			currentCenter.y = p[0];
      CGPathAddLineToPoint(path, NULL, currentPoint.x, currentPoint.y);
			//NSLog(@"V: %f", p[0]);
		}
		else if (type == SVG_path_VERTICAL_LINETO_RELATIVE) {
			currentPoint.y += p[0];
			currentCenter.y += p[0];
      CGPathAddLineToPoint(path, NULL, currentPoint.x, currentPoint.y);
			//NSLog(@"v: %f", p[0]);
		}
		else if (type == SVG_path_CURVETO_ABSOLUTE) {
      currentPoint.x = p[4];
      currentPoint.y = p[5];
      currentCenter.x = p[2];
      currentCenter.y = p[3];
			CGPathAddCurveToPoint(path, NULL, p[0], p[1], currentCenter.x, currentCenter.y, currentPoint.x, currentPoint.y);
			//NSLog(@"C: %f, %f, %f, %f, %f, %f", p[0], p[1], p[2], p[3], p[4], p[5]);
		}
		else if (type == SVG_path_CURVETO_RELATIVE) {
      x1 = p[0] + currentPoint.x;
      y1 = p[1] + currentPoint.y;
      currentPoint.x += p[4];
      currentPoint.y += p[5];
      currentCenter.x += p[2];
      currentCenter.y += p[3];
			CGPathAddCurveToPoint(path, NULL, x1, y1, currentCenter.x, currentCenter.y, currentPoint.x, currentPoint.y);
			//NSLog(@"c: %f, %f, %f, %f, %f, %f", p[0], p[1], p[2], p[3], p[4], p[5]);
		}
		else if (type == SVG_path_SMOOTH_CURVETO_ABSOLUTE) {
      // ALL GOOD
      x1 = currentPoint.x * 2 - currentCenter.x;
      y1 = currentPoint.y * 2 - currentCenter.y;
      x2 = p[0];
      y2 = p[1];
      x = p[2];
      y = p[3];
			CGPathAddCurveToPoint(path, NULL, x1, y1, x2, y2, x, y);
      currentPoint = CGPointMake(x, y);
      currentCenter = CGPointMake(x2, y2);
			//NSLog(@"S: %f, %f, %f, %f", p[0], p[1], p[2], p[3]);
		}
		else if (type == SVG_path_SMOOTH_CURVETO_RELATIVE) {
      // ALL GOOD
      x1 = currentPoint.x * 2 - currentCenter.x;
      y1 = currentPoint.y * 2 - currentCenter.y;
      x2 = p[0] + currentPoint.x;
      y2 = p[1] + currentPoint.y;
      x = p[2] + currentPoint.x;
      y = p[3] + currentPoint.y;
			CGPathAddCurveToPoint(path, NULL, x1, y1, x2, y2, x, y);
      currentPoint = CGPointMake(x, y);
      currentCenter = CGPointMake(x2, y2);
			//NSLog(@"s: %f, %f, %f, %f", p[0], p[1], p[2], p[3]);
		}
		else if (type == SVG_path_QUADRATIC_BEZIER_CURVETO_ABSOLUTE) {
      // ALL GOOD
      x1 = p[0];
      y2 = p[1];
      x = p[2];
      y = p[3];
			CGPathAddQuadCurveToPoint(path, NULL, x1, y1, x, y);
      currentPoint = CGPointMake(x, y);
      currentCenter = CGPointMake(x1, y1);
			//NSLog(@"Q: %f, %f, %f, %f", p[0], p[1], p[2], p[3]);
		}
		else if (type == SVG_path_QUADRATIC_BEZIER_CURVETO_RELATIVE) {
      // ALL GOOD
      x1 = p[0] + currentPoint.x;
      y1 = p[1] + currentPoint.y;
      x = p[2] + currentPoint.x;
      y = p[3] + currentPoint.y;
			CGPathAddQuadCurveToPoint(path, NULL, x1, y1, x2, y2);
      currentPoint = CGPointMake(x, y);
      currentCenter = CGPointMake(x1, y1);
			//NSLog(@"q: %f, %f, %f, %f", p[0], p[1], p[2], p[3]);
		}
		else if (type == SVG_path_SMOOTH_QUADRATIC_BEZIER_CURVETO_ABSOLUTE) {
      // ALL GOOD
      x = p[0];
      y = p[1];
      x1 = currentPoint.x * 2 - currentCenter.x;
      y1 = currentPoint.y * 2 - currentCenter.y;
			CGPathAddQuadCurveToPoint(path, NULL, x1, y1, x, y);
      currentPoint = CGPointMake(x, y);
      currentCenter = CGPointMake(x1, y1);
			//NSLog(@"T: %f, %f", p[0], p[1]);
		}
		else if (type == SVG_path_SMOOTH_QUADRATIC_BEZIER_CURVETO_RELATIVE) {
      // ALL GOOD
      x1 = currentPoint.x * 2 - currentCenter.x;
      y1 = currentPoint.y * 2 - currentCenter.y;
      x = p[0] + currentPoint.x;
      y = p[1] + currentPoint.y;
			CGPathAddQuadCurveToPoint(path, NULL, x1, y1, x, y);
      currentPoint = CGPointMake(x, y);
      currentCenter = CGPointMake(x1, y1);
			//NSLog(@"t: %f, %f", p[0], p[1]);
		}
		else if (type == SVG_path_ELLIPTICAL_ARC_ABSOLUTE) {
			// not supported
		}
		else if (type == SVG_path_ELLIPTICAL_ARC_RELATIVE) {
			// not supported
		}
		//NSLog(@"currentPoint: %f, %f", currentPoint.x, currentPoint.y);
		//NSLog(@"currentCenter: %f, %f", currentCenter.x, currentCenter.y);
		free(command);
	}
  //NSLog(@"Done parsing path");
	return CGPathCreateCopy(path);
}

- (void)makePath:(CGContextRef)context
{
	CGContextAddPath(context, path);
}

@end
